package com.markerhub.shiro;

import cn.hutool.core.bean.BeanUtil;
import com.markerhub.entity.User;
import com.markerhub.service.UserService;
import com.markerhub.util.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @Desc
 * @Author madengling
 * @Time 2021/1/13 18:34
 */
@Slf4j
@Component
public class AccountRealm extends AuthorizingRealm {
    @Autowired
    JwtUtils jwtUtils;
    @Autowired
    UserService userService;
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //1.把AuthenticationToken强转为JwtToken
        JwtToken jwt = (JwtToken) token;
        log.info("jwt----------------->{}", jwt);
        //2.从JwtToken中获取user
        String userId = jwtUtils.getClaimByToken((String) jwt.getPrincipal()).getSubject();
        //3.调用数据库方法，从数据库中查询user对应的用户记录
        User user = userService.getById(Long.parseLong(userId));
        //4.若用户不存在，则可以抛出UnknownAccountException异常
        if(user == null) {
            throw new UnknownAccountException("账户不存在！");
        }
        //5.根据用户信息的情况，j决定是否需要抛出其他的AuthenticationException异常。
        if(user.getStatus() == -1) {
            throw new LockedAccountException("账户已被锁定！");
        }
        //6.根据用户的情况，来构建AuthenticationInfo对象并返回 通常使用的实体类为：SimpleAuthenticationInfo
        //以下信息都是从数据库中获取到的
        //①.principal：认证的实体信息，可以是user，也可以是数据表对应的用户的实体类对象
        //②.credentials：密码
        //③.realmName：当前Realm对象的name. 调用父类的getName()方法即可
        //④.盐值
        AccountProfile profile = new AccountProfile();
        BeanUtil.copyProperties(user, profile);
        log.info("profile----------------->{}", profile.toString());
        return new SimpleAuthenticationInfo(profile, jwt.getCredentials(), getName());
//        return new SimpleAuthenticationInfo(profile, jwt.getCredentials(), credentialsSalt getName());
    }
}
